package memandwritebackstage

import chisel3._
import chisel3.util._
import memandwritebackstage.MemExtOpCode.{MEXT_Width, _}
object MemExtOpCode{
  val MEXT_Width  = 4.U.getWidth
  val MEXT_lw = 0.U(MEXT_Width.W)
  val MEXT_lh = 1.U(MEXT_Width.W)
  val MEXT_lhu = 2.U(MEXT_Width.W)
  val MEXT_lb = 3.U(MEXT_Width.W)
  val MEXT_lbu = 4.U(MEXT_Width.W)
}
class MemExtInBus extends Bundle{
  val rawMemData = Input(UInt(32.W))
  val offset = UInt(2.W)
  val code = UInt(MEXT_Width.W)
}
class MemExtUnit extends Module{
  val io = IO(new Bundle{
    val in = Input(new MemExtInBus)
    val extMemData = Output(UInt(32.W))
  })
  val offset = io.in.offset
  val opCode = io.in.code
  val offsetedData = io.in.rawMemData >> offset
  assert(offsetedData.getWidth == 32)

  val lwAns = offsetedData
  val lhAns = {
    val sign32 = Wire(32.S)
    sign32 := offsetedData(15,0).asSInt()
    sign32.asUInt()
  }
  val lhuAns = {
    val unsign32 = Wire(32.U)
    unsign32 := offsetedData(15,0)
    unsign32
  }
  val lbAns = {
    val sign32 = Wire(32.S)
    sign32 := offsetedData(7,0).asSInt()
    sign32.asUInt()
  }
  val lbuAns = {
    val unsign32 = Wire(32.U)
    unsign32 := offsetedData(7,0)
    unsign32
  }
  io.extMemData := MuxCase(lwAns,Seq(
    (opCode === MEXT_lb) -> lbAns,
    (opCode === MEXT_lbu) -> lbuAns,
    (opCode === MEXT_lh) -> lhAns,
    (opCode === MEXT_lhu) -> lhuAns
    //, (opCode === MEXT_lw) -> lwAns
  ))
}
